﻿using DoNet.ApiHttpClient;
using DoNet.Common.Helpers;
using DoNet.Wechat.MP.Menu.Entitys;
using Microsoft.Extensions.Logging;

namespace DoNet.Wechat.MP.Menu
{
    /// <summary>
    /// 自定义菜单
    /// </summary>
    public class MenuApi : WechatMpBase
    {
        /// <summary>
        /// 
        /// </summary>
        /// <param name="provider"></param>
        public MenuApi(ILogger logger, IServiceProvider provider) : base(logger, provider)
        {

        }

        #region Common
        /// <summary>
        /// 从rootButtonList获取buttonGroup
        /// </summary>
        /// <param name="rootButtonList"></param>
        /// <param name="buttonGroup"></param>
        private void GetButtonGroup(List<MenuFull_RootButton> rootButtonList, ButtonGroupBase buttonGroup)
        {
            foreach (var rootButton in rootButtonList)
            {
                if (string.IsNullOrEmpty(rootButton.name))
                {
                    continue; //没有设置一级菜单
                }
                var availableSubButton = rootButton.sub_button == null ? 0 : rootButton.sub_button.Count(z => !string.IsNullOrEmpty(z.name)); //可用二级菜单按钮数量
                if (availableSubButton == 0)
                {
                    //底部单击按钮
                    var type = rootButton.type;
                    if (!string.IsNullOrWhiteSpace(type))
                    {
                        if (type.Equals("CLICK", StringComparison.OrdinalIgnoreCase))
                        {
                            if (!string.IsNullOrEmpty(rootButton.key))
                            {
                                //点击
                                buttonGroup.button.Add(new SingleClickButton()
                                {
                                    name = rootButton.name,
                                    key = rootButton.key,
                                    type = type
                                });
                            }
                            else
                            {
                                logger.LogError("单击按钮的key不能为空！");
                            }
                        }
                        else if (type.Equals("VIEW", StringComparison.OrdinalIgnoreCase))
                        {
                            //URL
                            buttonGroup.button.Add(new SingleViewButton()
                            {
                                name = rootButton.name,
                                url = rootButton.url,
                                type = type
                            });
                        }
                        else if (type.Equals("LOCATION_SELECT", StringComparison.OrdinalIgnoreCase))
                        {
                            //弹出地理位置选择器
                            buttonGroup.button.Add(new SingleLocationSelectButton()
                            {
                                name = rootButton.name,
                                key = rootButton.key,
                                type = type
                            });
                        }
                        else if (type.Equals("PIC_PHOTO_OR_ALBUM", StringComparison.OrdinalIgnoreCase))
                        {
                            //弹出拍照或者相册发图
                            buttonGroup.button.Add(new SinglePicPhotoOrAlbumButton()
                            {
                                name = rootButton.name,
                                key = rootButton.key,
                                type = type
                            });
                        }
                        else if (type.Equals("PIC_SYSPHOTO", StringComparison.OrdinalIgnoreCase))
                        {
                            //弹出系统拍照发图
                            buttonGroup.button.Add(new SinglePicSysphotoButton()
                            {
                                name = rootButton.name,
                                key = rootButton.key,
                                type = type
                            });
                        }
                        else if (type.Equals("PIC_WEIXIN", StringComparison.OrdinalIgnoreCase))
                        {
                            //弹出微信相册发图器
                            buttonGroup.button.Add(new SinglePicWeixinButton()
                            {
                                name = rootButton.name,
                                key = rootButton.key,
                                type = type
                            });
                        }
                        else if (type.Equals("SCANCODE_PUSH", StringComparison.OrdinalIgnoreCase))
                        {
                            //扫码推事件
                            buttonGroup.button.Add(new SingleScancodePushButton()
                            {
                                name = rootButton.name,
                                key = rootButton.key,
                                type = type
                            });
                        }
                        else if (type.Equals("MINIPROGRAM", StringComparison.OrdinalIgnoreCase))
                        {
                            //小程序
                            buttonGroup.button.Add(new SingleMiniprogramButton()
                            {
                                name = rootButton.name,
                                type = type,
                                appid = rootButton.appid,
                                pagepath = rootButton.pagepath
                            });
                        }
                        else if (type.Equals("MEDIA_ID", StringComparison.OrdinalIgnoreCase))
                        {
                            //图片、音频、视频、图文消息
                            buttonGroup.button.Add(new SingleMediaIdButton()
                            {
                                name = rootButton.name,
                                media_id = rootButton.media_id,
                                type = type
                            });
                        }
                        else if (type.Equals("VIEW_LIMITED", StringComparison.OrdinalIgnoreCase))
                        {
                            //跳转图文消息URL 永久素材类型只支持图文消息
                            buttonGroup.button.Add(new SingleViewLimitedButton()
                            {
                                name = rootButton.name,
                                media_id = rootButton.media_id,
                                type = type
                            });
                        }
                        else if (type.Equals("NEWS", StringComparison.OrdinalIgnoreCase))
                        {
                            //图文
                            buttonGroup.button.Add(new SingleNewsButton()
                            {
                                name = rootButton.name,
                                type = type,
                                value = rootButton.value,
                                news_info = rootButton.news_info
                            });
                        }
                        else if (type.Equals("VIDEO", StringComparison.OrdinalIgnoreCase))
                        {
                            //视频
                            buttonGroup.button.Add(new SingleVideoButton()
                            {
                                name = rootButton.name,
                                type = type,
                                value = rootButton.value
                            });
                        }
                        else if (type.Equals("VOICE", StringComparison.OrdinalIgnoreCase))
                        {
                            //音频
                            buttonGroup.button.Add(new SingleVoiceButton()
                            {
                                name = rootButton.name,
                                type = type,
                                value = rootButton.value
                            });
                        }
                        else if (type.Equals("TEXT", StringComparison.OrdinalIgnoreCase))
                        {
                            //文本
                            buttonGroup.button.Add(new SingleTextButton()
                            {
                                name = rootButton.name,
                                type = type,
                                value = rootButton.value
                            });
                        }
                        else if (type.Equals("IMG", StringComparison.OrdinalIgnoreCase))
                        {
                            //图片
                            buttonGroup.button.Add(new SingleImageButton()
                            {
                                name = rootButton.name,
                                type = type,
                                value = rootButton.value
                            });
                        }
                        else if (type.Equals("ARTICLE_ID", StringComparison.OrdinalIgnoreCase))
                        {
                            buttonGroup.button.Add(new SingleArticleIdButton()
                            {
                                name = rootButton.name,
                                article_id = rootButton.article_id,
                                type = type
                            });
                        }
                        else if (type.Equals("ARTICLE_VIEW_LIMITED", StringComparison.OrdinalIgnoreCase))
                        {
                            buttonGroup.button.Add(new SingleArticleViewLimitedButton()
                            {
                                name = rootButton.name,
                                article_id = rootButton.article_id,
                                type = type
                            });
                        }
                        else
                        {
                            //扫码推事件且弹出“消息接收中”提示框
                            buttonGroup.button.Add(new SingleScancodeWaitmsgButton()
                            {
                                name = rootButton.name,
                                key = rootButton.key,
                                type = type
                            });
                        }
                    }
                    else
                    {
                        logger.LogError("菜单按钮类型不能为空！");
                    }
                }
                //else if (availableSubButton < 2)
                //{
                //    throw new WeixinMenuException("子菜单至少需要填写2个！");
                //}
                else
                {
                    //底部二级菜单
                    var subButton = new SubButton(rootButton.name);
                    buttonGroup.button.Add(subButton);
                    if (rootButton.sub_button != null)
                    {
                        foreach (var subSubButton in rootButton.sub_button)
                        {
                            if (string.IsNullOrEmpty(subSubButton.name))
                            {
                                continue; //没有设置菜单
                            }

                            if (!string.IsNullOrWhiteSpace(subSubButton.type))
                            {
                                if (subSubButton.type.Equals("CLICK", StringComparison.OrdinalIgnoreCase))
                                {
                                    if (!string.IsNullOrEmpty(subSubButton.key))
                                    {
                                        //点击
                                        subButton.sub_button.Add(new SingleClickButton()
                                        {
                                            name = subSubButton.name,
                                            key = subSubButton.key,
                                            type = subSubButton.type
                                        });
                                    }
                                    else
                                    {
                                        logger.LogError("二级菜单单击按钮的key不能为空！");
                                    }
                                }
                                else if (subSubButton.type.Equals("VIEW", StringComparison.OrdinalIgnoreCase))
                                {
                                    //URL
                                    subButton.sub_button.Add(new SingleViewButton()
                                    {
                                        name = subSubButton.name,
                                        url = subSubButton.url,
                                        type = subSubButton.type
                                    });
                                }
                                else if (subSubButton.type.Equals("LOCATION_SELECT", StringComparison.OrdinalIgnoreCase))
                                {
                                    //弹出地理位置选择器
                                    subButton.sub_button.Add(new SingleLocationSelectButton()
                                    {
                                        name = subSubButton.name,
                                        key = subSubButton.key,
                                        type = subSubButton.type
                                    });
                                }
                                else if (subSubButton.type.Equals("PIC_PHOTO_OR_ALBUM", StringComparison.OrdinalIgnoreCase))
                                {
                                    //弹出拍照或者相册发图
                                    subButton.sub_button.Add(new SinglePicPhotoOrAlbumButton()
                                    {
                                        name = subSubButton.name,
                                        key = subSubButton.key,
                                        type = subSubButton.type
                                    });
                                }
                                else if (subSubButton.type.Equals("PIC_SYSPHOTO", StringComparison.OrdinalIgnoreCase))
                                {
                                    //弹出系统拍照发图
                                    subButton.sub_button.Add(new SinglePicSysphotoButton()
                                    {
                                        name = subSubButton.name,
                                        key = subSubButton.key,
                                        type = subSubButton.type
                                    });
                                }
                                else if (subSubButton.type.Equals("PIC_WEIXIN", StringComparison.OrdinalIgnoreCase))
                                {
                                    //弹出微信相册发图器
                                    subButton.sub_button.Add(new SinglePicWeixinButton()
                                    {
                                        name = subSubButton.name,
                                        key = subSubButton.key,
                                        type = subSubButton.type
                                    });
                                }
                                else if (subSubButton.type.Equals("SCANCODE_PUSH", StringComparison.OrdinalIgnoreCase))
                                {
                                    //扫码推事件
                                    subButton.sub_button.Add(new SingleScancodePushButton()
                                    {
                                        name = subSubButton.name,
                                        key = subSubButton.key,
                                        type = subSubButton.type
                                    });
                                }
                                else if (subSubButton.type.Equals("MINIPROGRAM", StringComparison.OrdinalIgnoreCase))
                                {
                                    //小程序
                                    subButton.sub_button.Add(new SingleMiniprogramButton()
                                    {
                                        name = subSubButton.name,
                                        url = subSubButton.url,
                                        type = subSubButton.type,
                                        appid = subSubButton.appid,
                                        pagepath = subSubButton.pagepath
                                    });
                                }
                                else if (subSubButton.type.Equals("MEDIA_ID", StringComparison.OrdinalIgnoreCase))
                                {
                                    //图片、音频、视频、图文消息
                                    subButton.sub_button.Add(new SingleMediaIdButton()
                                    {
                                        name = subSubButton.name,
                                        media_id = subSubButton.media_id,
                                        type = subSubButton.type
                                    });
                                }
                                else if (subSubButton.type.Equals("VIEW_LIMITED", StringComparison.OrdinalIgnoreCase))
                                {
                                    //跳转图文消息URL 永久素材类型只支持图文消息
                                    subButton.sub_button.Add(new SingleViewLimitedButton()
                                    {
                                        name = subSubButton.name,
                                        media_id = subSubButton.media_id,
                                        type = subSubButton.type
                                    });
                                }
                                else if (subSubButton.type.Equals("NEWS", StringComparison.OrdinalIgnoreCase))
                                {
                                    //图文
                                    subButton.sub_button.Add(new SingleNewsButton()
                                    {
                                        name = subSubButton.name,
                                        type = subSubButton.type,
                                        value = subSubButton.value,
                                        news_info = subSubButton.news_info
                                    });
                                }
                                else if (subSubButton.type.Equals("VIDEO", StringComparison.OrdinalIgnoreCase))
                                {
                                    //视频
                                    subButton.sub_button.Add(new SingleVideoButton()
                                    {
                                        name = subSubButton.name,
                                        type = subSubButton.type,
                                        value = subSubButton.value
                                    });
                                }
                                else if (subSubButton.type.Equals("VOICE", StringComparison.OrdinalIgnoreCase))
                                {
                                    //音频
                                    subButton.sub_button.Add(new SingleVoiceButton()
                                    {
                                        name = subSubButton.name,
                                        type = subSubButton.type,
                                        value = subSubButton.value
                                    });
                                }
                                else if (subSubButton.type.Equals("TEXT", StringComparison.OrdinalIgnoreCase))
                                {
                                    //文本
                                    subButton.sub_button.Add(new SingleTextButton()
                                    {
                                        name = subSubButton.name,
                                        type = subSubButton.type,
                                        value = subSubButton.value
                                    });
                                }
                                else if (subSubButton.type.Equals("IMG", StringComparison.OrdinalIgnoreCase))
                                {
                                    //图片
                                    subButton.sub_button.Add(new SingleImageButton()
                                    {
                                        name = subSubButton.name,
                                        type = subSubButton.type,
                                        value = subSubButton.value
                                    });
                                }
                                else if (subSubButton.type.Equals("ARTICLE_ID", StringComparison.OrdinalIgnoreCase))
                                {
                                    subButton.sub_button.Add(new SingleArticleIdButton()
                                    {
                                        name = subSubButton.name,
                                        article_id = subSubButton.article_id,
                                        type = subSubButton.type
                                    });
                                }
                                else if (subSubButton.type.Equals("ARTICLE_VIEW_LIMITED", StringComparison.OrdinalIgnoreCase))
                                {
                                    subButton.sub_button.Add(new SingleArticleViewLimitedButton()
                                    {
                                        name = subSubButton.name,
                                        article_id = subSubButton.article_id,
                                        type = subSubButton.type
                                    });
                                }
                                else
                                {
                                    //扫码推事件且弹出“消息接收中”提示框
                                    subButton.sub_button.Add(new SingleScancodeWaitmsgButton()
                                    {
                                        name = subSubButton.name,
                                        key = subSubButton.key,
                                        type = subSubButton.type
                                    });
                                }
                            }
                            else
                            {
                                logger.LogError("二级菜单按钮类型不能为空！");
                            }
                        }
                    }
                }
            }
        }
        /// <summary>
        /// 根据微信返回的Json数据得到可用的GetMenuResult结果
        /// </summary>
        /// <param name="resultFull"></param>
        /// <param name="buttonGroupBase">ButtonGroupBase的衍生类型，可以为ButtonGroup或ConditionalButtonGroup。返回的GetMenuResult中的menu属性即为此示例。</param>
        /// <returns></returns>
        public GetMenuResult? GetMenuFromJsonResult(GetMenuResultFull resultFull, ButtonGroupBase buttonGroupBase)
        {
            if (buttonGroupBase != null)
            {
                try
                {
                    //重新整理按钮信息
                    ButtonGroupBase buttonGroup = buttonGroupBase; // ?? new ButtonGroup();
                    var rootButtonList = resultFull.menu.button;

                    GetButtonGroup(rootButtonList, buttonGroup);//设置默认菜单
                    GetMenuResult result = new GetMenuResult(buttonGroupBase)
                    {
                        menu = buttonGroup
                    };

                    //设置个性化菜单列表
                    if (resultFull.conditionalmenu != null)
                    {
                        var conditionalMenuList = new List<ConditionalButtonGroup>();
                        foreach (var conditionalMenu in resultFull.conditionalmenu)
                        {
                            var conditionalButtonGroup = new ConditionalButtonGroup();
                            //fix bug 16030701  https://github.com/JeffreySu/WeiXinMPSDK/issues/169
                            conditionalButtonGroup.matchrule = conditionalMenu.matchrule;
                            conditionalButtonGroup.menuid = conditionalMenu.menuid;
                            //fix bug 16030701 end

                            GetButtonGroup(conditionalMenu.button, conditionalButtonGroup);//设置默认菜单
                            conditionalMenuList.Add(conditionalButtonGroup);
                        }
                        result.conditionalmenu = conditionalMenuList;
                    }
                    return result;
                }
                catch (Exception ex)
                {
                    logger.LogError(ex.ToString());
                }
            }
            else
            {
                logger.LogError("buttonGroupBase不可以为空！");
            }
            return null;
        }
        /// 根据微信返回的Json数据得到可用的GetMenuResult结果
        /// </summary>
        /// <param name="resultFull"></param>
        /// <param name="buttonGroupBase">ButtonGroupBase的衍生类型，可以为ButtonGroup或ConditionalButtonGroup。返回的GetMenuResult中的menu属性即为此示例。</param>
        /// <returns></returns>
        public GetSelfMenuResult? GetSelfMenuFromJsonResult(GetSelfMenuResultFull resultFull, ButtonGroupBase buttonGroupBase)
        {
            if (buttonGroupBase != null)
            {
                try
                {
                    //重新整理按钮信息
                    ButtonGroupBase buttonGroup = buttonGroupBase; // ?? new ButtonGroup();
                    var rootButtonList = resultFull.selfmenu_info.button;

                    GetButtonGroup(rootButtonList, buttonGroup);//设置默认菜单
                    return new GetSelfMenuResult(buttonGroupBase)
                    {
                        is_menu_open = resultFull.is_menu_open,
                        selfmenu_info = buttonGroup
                    };
                }
                catch (Exception ex)
                {
                    logger.LogError(ex.ToString());
                }
            }
            else
            {
                logger.LogError("buttonGroupBase不可以为空！");
            }
            return null;
        }
        #endregion

        /// <summary>
        /// 创建菜单
        /// </summary>
        /// <param name="access_token"></param>
        /// <param name="buttonData">菜单内容</param>
        /// <returns></returns>
        public CreateMenuResult? CreateMenu(string access_token, MenuFull_ButtonGroup buttonData)
        {
            try
            {
                if (wechatApiService != null)
                {
                    ButtonGroupBase buttonGroup = new ButtonGroup();
                    GetButtonGroup(buttonData.button, buttonGroup);

                    Dictionary<string, object> param = new Dictionary<string, object>();
                    param.Add("button", buttonGroup.button);

                    var response = wechatApiService.SendRequest(HttpMethod.Post, $"cgi-bin/menu/create?access_token={access_token}", param);
                    HttpClientResponse httpClientResponse = new HttpClientResponse(response);
                    httpClientResponse.GetResponseBody();
                    if (httpClientResponse.IsResponse)
                    {
                        if (!string.IsNullOrWhiteSpace(httpClientResponse.ResponseBody))
                        {
                            var returnData = JsonHelper.DeserializeObject<CreateMenuResult>(httpClientResponse.ResponseBody);
                            if (returnData != null)
                            {
                                return returnData;
                            }
                        }
                    }
                }
            }
            catch (Exception ex)
            {
                logger.LogError(ex.ToString());
            }
            return null;
        }

        /// <summary>
        /// 查询接口
        /// 本接口将会提供公众号当前使用的自定义菜单的配置，如果公众号是通过API调用设置的菜单，则返回菜单的开发配置，而如果公众号是在公众平台官网通过网站功能发布菜单，则本接口返回运营者设置的菜单配置。
        /// </summary>
        /// <param name="access_token"></param>
        /// <returns></returns>
        public dynamic? GetCurrentMenu(string access_token)
        {
            try
            {
                if (wechatApiService != null)
                {
                    var response = wechatApiService.SendRequest(HttpMethod.Get, $"cgi-bin/get_current_selfmenu_info?access_token={access_token}");
                    HttpClientResponse httpClientResponse = new HttpClientResponse(response);
                    httpClientResponse.GetResponseBody();
                    if (httpClientResponse.IsResponse)
                    {
                        if (!string.IsNullOrWhiteSpace(httpClientResponse.ResponseBody))
                        {
                            var returnData = JsonHelper.DeserializeObject<dynamic>(httpClientResponse.ResponseBody);
                            if (returnData != null)
                            {
                                return returnData;
                            }
                        }
                    }
                }
            }
            catch (Exception ex)
            {
                logger.LogError(ex.ToString());
            }
            return default;
        }
        /// <summary>
        /// 查询接口
        /// 本接口将会提供公众号当前使用的自定义菜单的配置，如果公众号是通过API调用设置的菜单，则返回菜单的开发配置，而如果公众号是在公众平台官网通过网站功能发布菜单，则本接口返回运营者设置的菜单配置。
        /// </summary>
        /// <param name="access_token"></param>
        /// <returns></returns>
        public GetSelfMenuResult? GetCurrentSelfMenuInfo(string access_token)
        {
            try
            {
                var responseBody = GetCurrentMenu(access_token);
                if (responseBody != null)
                {
                    var errcode = (int)(responseBody.errcode ?? 0);
                    if (errcode == 0)
                    {
                        var returnData = JsonHelper.DeserializeObject<GetSelfMenuResultFull>(responseBody);
                        if (returnData != null)
                        {
                            if (returnData.selfmenu_info != null && returnData.selfmenu_info.button.Count > 0)
                            {
                                return GetSelfMenuFromJsonResult(returnData, new ButtonGroup());
                            }
                        }
                    }
                    else
                    {
                        logger.LogError((string)(responseBody.errmsg ?? string.Empty));
                    }
                }
            }
            catch (Exception ex)
            {
                logger.LogError(ex.ToString());
            }
            return null;
        }
        /// <summary>
        /// 获取自定义菜单配置
        /// 使用接口创建自定义菜单后，开发者还可使用接口查询自定义菜单的结构。另外请注意，在设置了个性化菜单后，使用本自定义菜单查询接口可以获取默认菜单和全部个性化菜单信息。
        /// </summary>
        /// <param name="access_token"></param>
        /// <returns></returns>
        public dynamic? GetMenuText(string access_token)
        {
            try
            {
                if (wechatApiService != null)
                {
                    var response = wechatApiService.SendRequest(HttpMethod.Get, $"cgi-bin/menu/get?access_token={access_token}");
                    HttpClientResponse httpClientResponse = new HttpClientResponse(response);
                    httpClientResponse.GetResponseBody();
                    if (httpClientResponse.IsResponse)
                    {
                        if (!string.IsNullOrWhiteSpace(httpClientResponse.ResponseBody))
                        {
                            var returnData = JsonHelper.DeserializeObject<dynamic>(httpClientResponse.ResponseBody);
                            if (returnData != null)
                            {
                                return returnData;
                            }
                        }
                    }
                }
            }
            catch (Exception ex)
            {
                logger.LogError(ex.ToString());
            }
            return default;
        }
        /// <summary>
        /// 获取自定义菜单配置
        /// 使用接口创建自定义菜单后，开发者还可使用接口查询自定义菜单的结构。另外请注意，在设置了个性化菜单后，使用本自定义菜单查询接口可以获取默认菜单和全部个性化菜单信息。
        /// </summary>
        /// <param name="access_token"></param>
        /// <returns></returns>
        public GetMenuResult? GetMenu(string access_token)
        {
            try
            {
                var responseBody = GetMenuText(access_token);
                if (responseBody != null)
                {
                    if (responseBody.errcode == 0)
                    {
                        var returnData = JsonHelper.DeserializeObject<GetMenuResultFull>(responseBody);
                        if (returnData != null)
                        {
                            if (returnData.menu != null && returnData.menu.button.Count > 0)
                            {
                                return GetMenuFromJsonResult(returnData, new ButtonGroup());
                            }
                        }
                    }
                    else
                    {
                        logger.LogError((string)responseBody.errmsg);
                    }
                }
            }
            catch (Exception ex)
            {
                logger.LogError(ex.ToString());
            }
            return null;
        }
        /// <summary>
        /// 删除菜单
        /// </summary>
        /// <param name="access_token"></param>
        /// <returns></returns>
        public DeleteMenuResult? DeleteMenu(string access_token)
        {
            try
            {
                if (wechatApiService != null)
                {
                    var response = wechatApiService.SendRequest(HttpMethod.Get, $"cgi-bin/menu/delete?access_token={access_token}");
                    HttpClientResponse httpClientResponse = new HttpClientResponse(response);
                    httpClientResponse.GetResponseBody();
                    if (httpClientResponse.IsResponse)
                    {
                        if (!string.IsNullOrWhiteSpace(httpClientResponse.ResponseBody))
                        {
                            var returnData = JsonHelper.DeserializeObject<DeleteMenuResult>(httpClientResponse.ResponseBody);
                            if (returnData != null)
                            {
                                if (returnData.errcode == 0)
                                {
                                    return returnData;
                                }
                                else
                                {
                                    logger.LogError(returnData.errmsg);
                                }
                            }
                        }
                    }
                }
            }
            catch (Exception ex)
            {
                logger.LogError(ex.ToString());
            }
            return null;
        }
    }
}
